---
title: Server Components
description: "Creating React components"
canonical: "/docs/react/server-components"
---

# Server Components

ReScript allows you to create server components as described in [React 19](https://react.dev/reference/rsc/server-components).

## Server Functions

To mark a file exposing functions as [Server Functions](https://react.dev/reference/rsc/server-functions),  
you can use the `@@directive("'use server'")` tag.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// src/actions/MyActions.res
@@directive("'use server'")

let myHelper = () => "Hello from the server!"

let helloWorld = async () => {
  let response = myHelper()
  response
}
```

```js
"use server";
// Generated by ReScript, PLEASE EDIT WITH CARE

function myHelper() {
  return "Hello from the server!";
}

async function helloWorld() {
  return "Hello from the server!";
}

export { myHelper, helloWorld };
```

</CodeTab>

**Warning:** It is recommended to use an interface file here, to ensure only the functions you want to expose are exposed.

```res
// src/actions/MyActions.resi
let helloWorld: unit => Promise<string>
```

`myHelper` will remain unexported with this change.

## Server Components

[Server components](https://react.dev/reference/rsc/server-components) can be async.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// src/pages/Index.res
let data = [1, 2, 3]
let getData = () => Promise.resolve(data)

@react.component
let make = async () => {
  // fetch some data from somewhere
  let data = await getData()
  <html>
    <body>
      <h1> {React.string("Hello from server component")} </h1>
      <ul>
        {data->Array.map(id => <li> {React.int(id)} </li>)->React.array}
      </ul>
    </body>
  </html>
}

// Export as default
let default = make
```

```js
"use server";
import * as JsxRuntime from "react/jsx-runtime";

async function make(param) {
  await getData();
  return JsxRuntime.jsx("html", {
    children: JsxRuntime.jsx("body", {
      children: JsxRuntime.jsx("h1", {
        children: "Hello from server component",
      }),
    }),
  });
}

let Index = make;

let make$1 = Index;

let $$default = Index;

export { make$1 as make, $$default as default };
```

</CodeTab>

A server function can be inlined in a server component and passed as prop to a client component.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
module ClientComp = {
  @react.component @module("some-module")
  external make: (~submit: int => promise<bool>) => React.element =
    "SomeClientComp"
}

let data = [1, 2, 3]
let getData = () => Promise.resolve(data)

@react.component
let make = async () => {
  let data = await getData()

  let addData =
    @directive("'use server'")
    async (id: int) => {
      // add to data store
      data->Array.push(id)
      true
    }
  <html>
    <body>
      <h1> {React.string("Hello from server component")} </h1>
      <ul>
        {data->Array.map(id => <li> {React.int(id)} </li>)->React.array}
      </ul>
      <ClientComp submit={addData} />
    </body>
  </html>
}
```

```js
import * as SomeModule from "some-module";

let data = [1, 2, 3];

function getData() {
  return Promise.resolve(data);
}

async function make(param) {
  let data$1 = await Promise.resolve(data);
  let addData = async (id) => {
    "use server";
    data$1.push(id);
    return true;
  };
  return JsxRuntime.jsx("html", {
    children: JsxRuntime.jsxs("body", {
      children: [
        JsxRuntime.jsx("h1", {
          children: "Hello from server component",
        }),
        JsxRuntime.jsx("ul", {
          children: data$1.map((id) =>
            JsxRuntime.jsx("li", {
              children: id,
            }),
          ),
        }),
        JsxRuntime.jsx(SomeModule.SomeClientComp, {
          submit: addData,
        }),
      ],
    }),
  });
}
```

</CodeTab>

**Note** that when decorating the function with `@directive("'use server'")`, we use a single `@`, where to annotate an entire file we use `@@directive("'use server'")`.

## Client Components

[Client components](https://react.dev/reference/rsc/use-client) should use the `@@directive("'use client'")` attribute.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
// src/components/ClientComp.res
@@directive("'use client'")

@react.component
let make = (~submit) => <button> {React.string("yow from client")} </button>
```

```js
use client'
// Generated by ReScript, PLEASE EDIT WITH CARE

import * as JsxRuntime from "react/jsx-runtime";

function ClientComp(props) {
  return JsxRuntime.jsx("button", {
    children: "yow from client"
  });
}

let make = ClientComp;

export {
  make,
}
```

</CodeTab>
